﻿using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading;

namespace roguelike
{
    public class Rooms
    {
        public Rooms(int startW, int startH,int h,int w)
        {
            H = h;
            W = w;
            StartH = startH;
            StartW = startW;
        }
        public int W { get; set; }
        public int H { get; set; }
        public int StartW { get; set; }
        public int StartH { get; set; }
    }


    
    public class Map
    {
        public int[,] Matrix { get; set; }
        private readonly List<Rooms> rooms = new List<Rooms>();
        private readonly int count = 0;


        

        public Map(int h, int w)
        {
            Matrix = new int[h, w];
            var gen = new Random();
            int k = 0;

            #region Генерация комнат
            while (k < 1000)
            {
                int startH = gen.Next(1, h);
                int startW = gen.Next(1, w);
                int genI = gen.Next(2, 5) * 2 + 1;
                int genJ = gen.Next(2, 5) * 2 + 1;
                k++;
                if ((startH + genI + 1 < h) & (startW + genJ + 1 < w) & (genI * genJ > 3))
                {
                    int check = 0;
                    for (int x = 0; x < genI; x++)
                        for (int y = 0; y < genJ; y++)
                            check += Matrix[startH + x, startW + y];
                    if (check == 0)
                    {
                        var room = new Rooms(startW + genJ / 2, startH + genI / 2,genI,genJ);
                        rooms.Add(room);
                        for (int x = 0; x < genI + 2; x++)
                            for (int y = 0; y < genJ + 2; y++)
                                Matrix[startH - 1 + x, startW - 1 + y] = 1;
                        for (int x = 0; x < genI; x++)
                            for (int y = 0; y < genJ; y++)
                            {
                                Matrix[startH + x, startW + y] = 2;
                            }
                        k++;
                    }
                }
            }
            for (int i = 0; i < w; i++)
            {
                for (int j = 0; j < h; j++)
                    if (Matrix[j, i] == 1)
                    {
                        Matrix[j, i] = 3;
                        break;
                    }
            }
            for (int i = 0; i < w; i++)
            {
                for (int j = h - 1; j > 0; j--)
                    if (Matrix[j, i] == 1)
                    {
                        Matrix[j, i] = 3;
                        break;
                    }
            }
            for (int i = 0; i < h; i++)
            {
                for (int j = 0; j < w; j++)
                    if (Matrix[i, j] == 1)
                    {
                        Matrix[i, j] = 3;
                        break;
                    }
            }
            for (int i = 0; i < h; i++)
            {
                for (int j = w - 1; j > 0; j--)
                    if (Matrix[i, j] == 1)
                    {
                        Matrix[i, j] = 3;
                        break;
                    }
            }
            #endregion

            #region построение коридоров
            foreach (Rooms item in rooms)
            {
                bool check = false;
                while (!check)
                {
                    int choice = gen.Next(0, 4);
                    switch (choice)
                    {
                        case 0:
                            check = UpCorridor(item);
                            break;
                        case 1:
                            check = DownCorridor(item);
                            break;
                        case 2:
                            check = LeftCorridor(item);
                            break;
                        case 3:
                            check = RightCorridor(item);
                            break;
                    }
                }
            }
            foreach (Rooms item in rooms)
            {
                bool check = false;

                if (count % 2 == 0)
                {
                    while (!check)
                    {
                        int choice = gen.Next(0, 4);
                        switch (choice)
                        {
                            case 0:
                                check = UpCorridor(item);
                                break;
                            case 1:
                                check = DownCorridor(item);
                                break;
                            case 2:
                                check = LeftCorridor(item);
                                break;
                            case 3:
                                check = RightCorridor(item);
                                break;
                            default:
                                Console.WriteLine("Error");
                                break;
                        }
       
                    }
                }
                count++;
            }

   

           
        }

       

        public bool UpCorridor(Rooms item)
        {
            var rand = new Random();
            int B = 0;
            bool check = false;
            int U =0;
            //int point = item.StartH;
            //int M = 0;
            //while (Matrix[point,item.StartW]==2 || M>10)
            //{

            //    point--;
            //    M++;
            //}
            
            //for (int i = -3; i < 3; i++)
            //{
            //    if (Matrix[point, item.StartW + i] == 2)
            //    {
            //        return false;
            //    }

            //}

            while (U < 30)
            {
               int temp = 0;
               int test = rand.Next(-2, 3);

                while (B != 3)
                {
                    if (Matrix[item.StartH - temp, item.StartW+test] == 3)
                    {
                        break;
                    }
                    if (Matrix[item.StartH - temp, item.StartW + test] == 1)
                    {
                        if (Matrix[item.StartH - temp - 1, item.StartW + test] == 2)
                        {
                            check = true;
                            break;
                        }
                        B++;
                    }
                    temp++;
                }
                if (check)
                {
                    int temp2 = 0;
                    int T = 0;
                    while (T != 2)
                    {
                        if (Matrix[item.StartH - temp2, item.StartW + test] == 3)
                            break;
                        if (Matrix[item.StartH - temp2, item.StartW + test] == 1)
                        {
                            if (Matrix[item.StartH - temp2 - 1, item.StartW + test] == 2)
                            {
                                Matrix[item.StartH - temp2, item.StartW + test] = 4;
                                break;
                            }
                            Matrix[item.StartH - temp2, item.StartW + test] = 4;
                            T++;
                        }
                        if (Matrix[item.StartH - temp2, item.StartW + test] != 4)
                        {
                            Matrix[item.StartH - temp2, item.StartW + test] = 2;
                            if (item.StartW + test - 1 > 0 && item.StartW + test + 1 < Matrix.GetLength(0))
                            {
                                if (Matrix[item.StartH - temp2, item.StartW + test - 1] == 0)
                                {
                                    Matrix[item.StartH - temp2, item.StartW + test - 1] = 1;
                                }
                                if (Matrix[item.StartH - temp2, item.StartW + test + 1] == 0)
                                {
                                    Matrix[item.StartH - temp2, item.StartW + test + 1] = 1;
                                }
                            }
                        }
                        temp2++;
                    }
                }
                if (check)
                {
                    break;
                }
                U++;
            }
            return check;
        }
        public bool DownCorridor(Rooms item)
        {
    
            int b = 0;

            bool check = false;
            var rand = new Random();
            int U =0;
            //int point = item.StartH;
            //int M = 0;
            //while (Matrix[point, item.StartW] == 2 || M > 10)
            //{
            //    point++;
            //    M++;
            //}

            //for (int i = -3; i < 3; i++)
            //{
            //    if (Matrix[point , item.StartW + i] == 2)
            //    {
            //        return false;
            //    }

            //}

            while (U < 30)
            {
                int temp = 0;
                int test = rand.Next(-2, 3);
                while (b != 3)
                {
                    if (Matrix[item.StartH + temp, item.StartW + test] == 3)
                    {
                        break;
                    }

                    if (Matrix[item.StartH + temp, item.StartW + test] == 1)
                    {
                        if (Matrix[item.StartH + temp + 1, item.StartW + test] == 2)
                        {
                            check = true;
                            break;
                        }
                        b++;
                    }
                    temp++;
                }
                if (check)
                {
                    int temp2 = 0;
                    int t = 0;
                    while (t != 2)
                    {
                        if (Matrix[item.StartH + temp2, item.StartW + test] == 3)
                            break;
                        if (Matrix[item.StartH + temp2, item.StartW + test] == 1)
                        {
                            if (Matrix[item.StartH + temp2 + 1, item.StartW + test] == 2)
                            {
                                Matrix[item.StartH + temp2, item.StartW + test] = 4;
                                break;
                            }
                            Matrix[item.StartH + temp2, item.StartW + test] = 4;
                            t++;
                        }
                        if (Matrix[item.StartH + temp2, item.StartW + test] != 4)
                        {
                            Matrix[item.StartH + temp2, item.StartW + test] = 2;

                            if (item.StartW + test - 1 > 0 && item.StartW + test + 1 < Matrix.GetLength(0))
                            {
                                if (Matrix[item.StartH + temp2, item.StartW + test - 1] == 0)
                                {
                                    Matrix[item.StartH + temp2, item.StartW + test - 1] = 1;
                                }
                                if (Matrix[item.StartH + temp2, item.StartW + test + 1] == 0)
                                {
                                    Matrix[item.StartH + temp2, item.StartW + test + 1] = 1;
                                }
                            }
                        }
                        temp2++;
                    }
                }
                if (check)
                {
                    break;
                    
                }
                U++;
            }
            return check;
        }
        public bool LeftCorridor(Rooms item)
        {
            int b = 0;

            bool check = false;
            var rand = new Random();
            int U =0;
            while (U < 30)
            {
                int temp = 0;
                int test = rand.Next(-2, 3);
                while (b != 3)
                {
                    if (Matrix[item.StartH + test, item.StartW - temp] == 3)
                    {
                        break;
                    }

                    if (Matrix[item.StartH + test, item.StartW - temp] == 1)
                    {
                        if (Matrix[item.StartH + test, item.StartW - temp - 1] == 2)
                        {
                            check = true;
                            break;
                        }
                        b++;
                    }
                    temp++;
                }
                if (check)
                {
                    int temp2 = 0;
                    int T = 0;
                    while (T != 2)
                    {
                        if (Matrix[item.StartH + test, item.StartW - temp2] == 3)
                            break;
                        if (Matrix[item.StartH + test, item.StartW - temp2] == 1)
                        {
                            if (Matrix[item.StartH + test, item.StartW - temp2 - 1] == 2)
                            {
                                Matrix[item.StartH + test, item.StartW - temp2] = 4;
                                break;
                            }
                            Matrix[item.StartH + test, item.StartW - temp2] = 4;
                            T++;
                        }
                        if (Matrix[item.StartH + test, item.StartW - temp2] != 4)
                        {
                            Matrix[item.StartH + test, item.StartW - temp2] = 2;
                            if (item.StartH + test - 1 > 0 && item.StartH + test + 1 < Matrix.GetLength(0))
                            {
                                if (Matrix[item.StartH + test - 1, item.StartW - temp2] == 0)
                                {
                                    Matrix[item.StartH + test - 1, item.StartW - temp2] = 1;
                                }
                                if (Matrix[item.StartH + test + 1, item.StartW - temp2] == 0)
                                {
                                    Matrix[item.StartH + test + 1, item.StartW - temp2] = 1;
                                }
                            }
                        }
                        temp2++;
                    }
                }
                if (check)
                {
                    break;
                }
                U++;
            }
            return check;
        }
        public bool RightCorridor(Rooms item)
        {
            int B = 0;

            bool check = false;
             var rand = new Random();
            int U =0;
            while (U < 30)
            {
                int temp = 0;
                int test = rand.Next(-2, 3);
                while (B != 3)
                {
                    if (Matrix[item.StartH + test, item.StartW + temp] == 3)
                    {
                        break;
                    }

                    if (Matrix[item.StartH + test, item.StartW + temp] == 1)
                    {
                        if (Matrix[item.StartH + test, item.StartW + temp + 1] == 2)
                        {
                            check = true;
                            break;
                        }
                        B++;
                    }
                    temp++;
                }
                if (check)
                {
                    int temp2 = 0;
                    int T = 0;
                    while (T != 2)
                    {
                        if (Matrix[item.StartH + test, item.StartW + temp2] == 3)
                            break;
                        if (Matrix[item.StartH + test, item.StartW + temp2] == 1)
                        {
                            if (Matrix[item.StartH + test, item.StartW + temp2 + 1] == 2)
                            {
                                Matrix[item.StartH + test, item.StartW + temp2] = 4;
                                break;
                            }
                            Matrix[item.StartH + test, item.StartW + temp2] = 4;
                            T++;
                        }
                        if (Matrix[item.StartH + test, item.StartW + temp2] != 4)
                        {
                            Matrix[item.StartH + test, item.StartW + temp2] = 2;
                            if (item.StartH + test - 1 > 0 && item.StartH + test + 1 < Matrix.GetLength(0))
                            {
                                if (Matrix[item.StartH + test + 1, item.StartW + temp2] == 0)
                                {
                                    Matrix[item.StartH + test + 1, item.StartW + temp2] = 1;
                                }
                                if (Matrix[item.StartH + test - 1, item.StartW + temp2] == 0)
                                {
                                    Matrix[item.StartH + test - 1, item.StartW + temp2] = 1;
                                }
                            }
                        }
                        temp2++;
                    }
                }
                if (check)
                {
                    break;
                }
                U++;
            }
            return check;
        }
            #endregion


    

  
    
    }
}
